//
//package com.geek.bams.server;
//
//import com.geek.bams.service.Bank;
//import com.geek.bams.utils.ThreadPool;
//
//import java.awt.*;
//import java.awt.event.*;
//import java.io.IOException;
//import java.net.ServerSocket;
//import java.net.Socket;
//import java.net.SocketException;
//import java.util.concurrent.BrokenBarrierException;
//import java.util.concurrent.CopyOnWriteArrayList;
//import java.util.concurrent.CyclicBarrier;
//import javax.swing.*;
//
//public class ServerPanel extends JPanel {
//
//    //网络编程资源
//    //服务端套接字
//    ServerSocket ss;
//    //客户端套接字
//    Socket s;
//
//    //线程池
//    ThreadPool pool;
//    //银行资源
//    Bank bank;
//    //线程安全的集合容器，存储所有接入客户端的Socket
//    CopyOnWriteArrayList<Socket> clients;
//
//    //标识 控制是否等待接入客户端
//    //默认false，不允许接入客户端
//    boolean accept = false;
//
//    public ServerPanel() {
//        bank = Bank.getInstance();
//        pool = new ThreadPool(40 , 3000);
//        clients = new CopyOnWriteArrayList<>();
//
//        initComponents();
//    }
//
//    //点击启动按钮,启动服务器
//    private void start(ActionEvent e) {
//        //计数器   当计数器累加至1，则开始执行任务
//        CyclicBarrier barrier = new CyclicBarrier(1 , ()->startWork());
//
//        if(ss==null){
//            //线程池中，派出线程执行任务
//            pool.exec(() ->{
//
//                try {
//                    //启动服务器
//                    ss = new ServerSocket(8899);
//                    JOptionPane.showMessageDialog(this, "服务器开启");
//
//                    //设置按钮状态
//                    startButton.setEnabled(false);
//                    closeButton.setEnabled(true);
//
//                    //设置允许接入客户端
//                    accept = true;
//
//                    //计数器 +1
//                    barrier.await();
//                } catch (IOException | InterruptedException | BrokenBarrierException ex) {
//                    throw new RuntimeException(ex);
//                }
//
//            });
//        }else{
//            JOptionPane.showMessageDialog(this, "服务器已启动！");
//        }
//    }
//
//    //开始执行任务  一旦计数器+1，达到循环屏障的条件，则会执行ss.accept()接入客户端的Socket，分配ServerTasker
//    //核心工作 一旦计数器+1后，达到循环屏障的条件， 则执行客户端接入，分配ServerTasker业务员
//    private void startWork(){
//        //通过accept开关控制，是否无限接入客户端
//        while (accept){
//            try {
//                //等待接入客户端
//                s = ss.accept();
//                System.out.println("客户端成功接入~");
//
//                //添加客户端，为其分配一位“业务员”并分配任务
//                if(s!=null && clients!=null){
//                    clients.add(s);
//                    //让线程池执行ServerTasker任务
//                    ServerTasker tasker = new ServerTasker(bank , s);
//                    pool.exec(tasker);
//                }
//            } catch (SocketException e) {
//                JOptionPane.showMessageDialog(this, "服务器已关闭！");
//            } catch (IOException e) {
//                throw new RuntimeException(e);
//            }
//        }
//    }
//
//    //点击关闭按钮,关闭服务器
//    private void close(ActionEvent e) {
//        if(ss==null){
//            JOptionPane.showMessageDialog(this, "服务器未开启！");
//            return;
//        }
//
//        //服务器开启状态，且未被关闭
//        if(ss!=null && !ss.isClosed()){
//            //---------------------释放客户端的资源---------------------
//            //迭代clients客户端，将其socket一一关闭
//            if(clients!=null && clients.size()>0){
//                clients.forEach(socket -> {
//                    if(socket!=null){
//                        try {
//                            socket.close();
//                        } catch (IOException ex) {
//                            throw new RuntimeException(ex);
//                        }
//                    }
//                });
//            }
//            //清空集合
//            clients.clear();
//
//            //设置按钮状态
//            startButton.setEnabled(true);
//            closeButton.setEnabled(false);
//
//            //改变无限接入客户端的标识,设置false表示不再接入客户端
//            accept = false;
//
//            //---------------------释放服务器资源---------------------
//            try {
//                ss.close();
//                ss = null;
//            } catch (IOException ex) {
//                JOptionPane.showMessageDialog(this, "服务器未正确关闭！");
//            }
//        }else{
//            JOptionPane.showMessageDialog(this, "服务器已关闭！");
//        }
//    }
//
//    //跳转至RankPanel界面,开启上帝视角
//    private void skipRank(ActionEvent e) {
//        //获取当前LoginPanel的父窗口（ATMClient），的布局方式，即卡片式布局
//        CardLayout card = (CardLayout)this.getParent().getLayout();
//        //指定跳转至主界面
//        card.show(this.getParent() , "rankPanel");
//    }
//
//    private void initComponents() {
//        // JFormDesigner - Component initialization - DO NOT MODIFY  //GEN-BEGIN:initComponents  @formatter:off
//        titleLabel = new JLabel();
//        startButton = new JButton();
//        closeButton = new JButton();
//        skipRankButton = new JButton();
//
//        //======== this ========
//        setLayout(null);
//
//        //---- titleLabel ----
//        titleLabel.setText("\u670d   \u52a1   \u5668");
//        titleLabel.setHorizontalAlignment(SwingConstants.CENTER);
//        titleLabel.setFont(new Font("Microsoft YaHei UI", Font.BOLD, 28));
//        add(titleLabel);
//        titleLabel.setBounds(150, 65, 185, 45);
//
//        //---- startButton ----
//        startButton.setText("\u542f\u52a8\u670d\u52a1\u5668");
//        startButton.setFont(new Font("Microsoft YaHei UI", Font.PLAIN, 16));
//        startButton.addActionListener(e -> start(e));
//        add(startButton);
//        startButton.setBounds(100, 245, 130, 40);
//
//        //---- closeButton ----
//        closeButton.setText("\u5173\u95ed\u670d\u52a1\u5668");
//        closeButton.setFont(new Font("Microsoft YaHei UI", Font.PLAIN, 16));
//        closeButton.addActionListener(e -> close(e));
//        add(closeButton);
//        closeButton.setBounds(325, 245, 130, 40);
//
//        //---- skipRankButton ----
//        skipRankButton.setText("\u5f00\u542f\u4e0a\u5e1d\u89c6\u89d2");
//        skipRankButton.setFont(new Font("Microsoft YaHei UI", Font.PLAIN, 16));
//        skipRankButton.addActionListener(e -> skipRank(e));
//        add(skipRankButton);
//        skipRankButton.setBounds(295, 395, 160, 40);
//
//        setPreferredSize(new Dimension(500, 650));
//        // JFormDesigner - End of component initialization  //GEN-END:initComponents  @formatter:on
//    }
//
//    // JFormDesigner - Variables declaration - DO NOT MODIFY  //GEN-BEGIN:variables  @formatter:off
//    private JLabel titleLabel;
//    private JButton startButton;
//    private JButton closeButton;
//    private JButton skipRankButton;
//    // JFormDesigner - End of variables declaration  //GEN-END:variables  @formatter:on
//}

package com.geek.bams.server;

import com.geek.bams.service.Bank;
import com.geek.bams.utils.ThreadPool;

import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Map;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CyclicBarrier;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ServerPanel extends JPanel {

    //网络编程资源
    //服务端套接字
    ServerSocket ss;
    //客户端套接字
    Socket s;

    //线程池
    ThreadPool pool;
    //银行资源
    Bank bank;
    //线程安全的集合容器，存储所有接入客户端的Socket
    CopyOnWriteArrayList<Socket> clients;

    //标识 控制是否等待接入客户端
    //默认false，不允许接入客户端
    boolean accept = false;

    // 添加定时器用于更新登录用户信息
    private ScheduledExecutorService scheduler;
    private DefaultTableModel tableModel;
    private JTable loginTable; // 添加这一行声明

    public ServerPanel() {
        bank = Bank.getInstance();
        pool = new ThreadPool(40 , 3000);
        clients = new CopyOnWriteArrayList<>();

        initComponents();
        initializeLoginTable(); // 替换原来的initLoginTable()
        startLoginInfoUpdater();
    }
    private void initializeLoginTable() {
        // 初始化表格模型
        String[] columnNames = {"账户ID", "IP地址"};
        tableModel = new DefaultTableModel(columnNames, 0);
        loginTable = new JTable(tableModel); // 创建JTable实例

        // 将表格放入滚动面板并添加到面板中
        JScrollPane scrollPane = new JScrollPane(loginTable);
        scrollPane.setBounds(50, 220, 400, 200); // 根据需要调整位置和大小
        add(scrollPane);
    }



    private void startLoginInfoUpdater() {
        // 创建定时任务，每2秒更新一次登录信息
        scheduler = Executors.newScheduledThreadPool(1);
        scheduler.scheduleAtFixedRate(this::updateLoginInfo, 0, 2, TimeUnit.SECONDS);
    }

    private void updateLoginInfo() {
        // 在EDT中更新UI
        SwingUtilities.invokeLater(() -> {
            // 清空现有数据
            tableModel.setRowCount(0);

            // 获取当前登录信息
            Map<Long, String> loginIpMap = ServerTasker.getLoginIpMap();

            // 添加数据到表格
            for (Map.Entry<Long, String> entry : loginIpMap.entrySet()) {
                Object[] row = {entry.getKey(), entry.getValue()};
                tableModel.addRow(row);
            }
        });
    }

    //点击启动按钮,启动服务器
    private void start(ActionEvent e) {
        //计数器   当计数器累加至1，则开始执行任务
        CyclicBarrier barrier = new CyclicBarrier(1 , ()->startWork());

        if(ss==null){
            //线程池中，派出线程执行任务
            pool.exec(() ->{

                try {
                    //启动服务器
                    ss = new ServerSocket(8899);
                    JOptionPane.showMessageDialog(this, "服务器开启");

                    //设置按钮状态
                    startButton.setEnabled(false);
                    closeButton.setEnabled(true);

                    //设置允许接入客户端
                    accept = true;

                    //计数器 +1
                    barrier.await();
                } catch (IOException | InterruptedException | BrokenBarrierException ex) {
                    throw new RuntimeException(ex);
                }

            });
        }else{
            JOptionPane.showMessageDialog(this, "服务器已启动！");
        }
    }

    //开始执行任务  一旦计数器+1，达到循环屏障的条件，则会执行ss.accept()接入客户端的Socket，分配ServerTasker
    //核心工作 一旦计数器+1后，达到循环屏障的条件， 则执行客户端接入，分配ServerTasker业务员
    private void startWork(){
        //通过accept开关控制，是否无限接入客户端
        while (accept){
            try {
                //等待接入客户端
                s = ss.accept();
                System.out.println("客户端成功接入~");

                //添加客户端，为其分配一位"业务员"并分配任务
                if(s!=null && clients!=null){
                    clients.add(s);
                    //让线程池执行ServerTasker任务
                    ServerTasker tasker = new ServerTasker(bank , s);
                    pool.exec(tasker);
                }
            } catch (SocketException e) {
                JOptionPane.showMessageDialog(this, "服务器已关闭！");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    //点击关闭按钮,关闭服务器
    private void close(ActionEvent e) {
        // 关闭定时器
        if (scheduler != null && !scheduler.isShutdown()) {
            scheduler.shutdown();
        }

        if(ss==null){
            JOptionPane.showMessageDialog(this, "服务器未开启！");
            return;
        }

        //服务器开启状态，且未被关闭
        if(ss!=null && !ss.isClosed()){
            //---------------------释放客户端的资源---------------------
            //迭代clients客户端，将其socket一一关闭
            if(clients!=null && clients.size()>0){
                clients.forEach(socket -> {
                    if(socket!=null){
                        try {
                            socket.close();
                        } catch (IOException ex) {
                            throw new RuntimeException(ex);
                        }
                    }
                });
            }
            //清空集合
            clients.clear();

            //设置按钮状态
            startButton.setEnabled(true);
            closeButton.setEnabled(false);

            //改变无限接入客户端的标识,设置false表示不再接入客户端
            accept = false;

            //---------------------释放服务器资源---------------------
            try {
                ss.close();
                ss = null;
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(this, "服务器未正确关闭！");
            }
        }else{
            JOptionPane.showMessageDialog(this, "服务器已关闭！");
        }
    }

    //跳转至RankPanel界面,开启上帝视角
    private void skipRank(ActionEvent e) {
        //获取当前LoginPanel的父窗口（ATMClient），的布局方式，即卡片式布局
        CardLayout card = (CardLayout)this.getParent().getLayout();
        //指定跳转至主界面
        card.show(this.getParent() , "rankPanel");
    }

    private void initComponents() {
        // JFormDesigner - Component initialization - DO NOT MODIFY  //GEN-BEGIN:initComponents  @formatter:off
        titleLabel = new JLabel();
        startButton = new JButton();
        closeButton = new JButton();
        skipRankButton = new JButton();

        //======== this ========
        setLayout(null);

        //---- titleLabel ----
        titleLabel.setText("\u670d   \u52a1   \u5668");
        titleLabel.setHorizontalAlignment(SwingConstants.CENTER);
        titleLabel.setFont(new Font("Microsoft YaHei UI", Font.BOLD, 28));
        add(titleLabel);
        titleLabel.setBounds(150, 65, 185, 45);

        //---- startButton ----
        startButton.setText("\u542f\u52a8\u670d\u52a1\u5668");
        startButton.setFont(new Font("Microsoft YaHei UI", Font.PLAIN, 16));
        startButton.addActionListener(e -> start(e));
        add(startButton);
        startButton.setBounds(70, 155, 130, 40);

        //---- closeButton ----
        closeButton.setText("\u5173\u95ed\u670d\u52a1\u5668");
        closeButton.setFont(new Font("Microsoft YaHei UI", Font.PLAIN, 16));
        closeButton.addActionListener(e -> close(e));
        add(closeButton);
        closeButton.setBounds(320, 155, 130, 40);

        //---- skipRankButton ----
        skipRankButton.setText("\u5f00\u542f\u4e0a\u5e1d\u89c6\u89d2");
        skipRankButton.setFont(new Font("Microsoft YaHei UI", Font.PLAIN, 16));
        skipRankButton.addActionListener(e -> skipRank(e));
        add(skipRankButton);
        skipRankButton.setBounds(320, 20, 160, 40);

        setPreferredSize(new Dimension(500, 650));
        // JFormDesigner - End of component initialization  //GEN-END:initComponents  @formatter:on
    }

    // JFormDesigner - Variables declaration - DO NOT MODIFY  //GEN-BEGIN:variables  @formatter:off
    private JLabel titleLabel;
    private JButton startButton;
    private JButton closeButton;
    private JButton skipRankButton;
    // JFormDesigner - End of variables declaration  //GEN-END:variables  @formatter:on
}
